use std::time::Duration;

use base_data::channel::{event::ChannelEvent, ChannelState, CommandMsg, EndReason};
use tools::{utils::gen_id::get_now_duration, ResultEx, ResultNull};
use tracing::{debug, error, trace};

use crate::sip2::{
	dialog::{
		dialog::{Dialog, DialogState},
		sipdata::SipData,
		INV_OVER, WAIT_REPEAT_TIME,
	},
	SipDirection,
};

use super::{send_wait_resp, SipTimeOver, SipTransaction, SipTransactionState, WaitSipMessage};

#[inline]
pub fn start_tran(dialog: &mut Dialog) {
	trace!("开始INVITE_CLIENT事务");
	dialog.set_tran_state(SipTransactionState::Callin);
	dialog.start_time = get_now_duration();
	dialog.wait_resp_method = WaitSipMessage::None;

	if dialog.over_time == SipTimeOver::Zero {
		dialog.over_time = SipTimeOver::TranOvertime(INV_OVER);
	}

	//在这里会设置重发的相关状态.上面不需要设置了
	if let Some(buf) = &dialog.last_send_bytes {
		send_wait_resp(dialog, WaitSipMessage::None, buf.clone());
	} else {
		error!("inv_client没有要发送的消息.....")
	}
}

///处理事务收到的传输层的消息
#[inline]
pub fn handle_tran_msg(dialog: &mut Dialog, sip_data: SipData) -> ResultNull {
	match sip_data.direction {
		SipDirection::Response(r) => match (r.into(), dialog.tran_state()) {
			(183, SipTransactionState::Callin) | (183, SipTransactionState::Proceeding) => {
				dialog.retry_time = Duration::ZERO;
				dialog.set_tran_state(SipTransactionState::Proceeding);
				dialog.last_send_bytes = None;
				
				dialog.set_sdp(&sip_data.body)?;
				dialog.state = DialogState::PreAnswer;
				dialog.send_to_business(ChannelEvent::ChannelCallState(
					dialog.id,
					ChannelState::Early,
				));
			}
			(180, SipTransactionState::Callin) | (180, SipTransactionState::Proceeding) => {
				dialog.retry_time = Duration::ZERO;
				dialog.set_tran_state(SipTransactionState::Proceeding);
				dialog.state = DialogState::Ringing;
				dialog.last_send_bytes = None;

				dialog.send_to_business(ChannelEvent::ChannelCallState(
					dialog.id,
					ChannelState::Ringing,
				));
			}
			(100..=199, SipTransactionState::Callin) => {
				dialog.retry_time = Duration::ZERO;
				dialog.last_send_bytes = None;
				dialog.set_tran_state(SipTransactionState::Proceeding);
			}
			(200..=299, SipTransactionState::Callin) | (200..=299, SipTransactionState::Proceeding) => {
				dialog.retry_time = Duration::ZERO;
				dialog.last_send_bytes = None;
				dialog.start_time = get_now_duration();
				dialog.over_time = SipTimeOver::Finish(Duration::ZERO);
				dialog.wait_resp_method = WaitSipMessage::None;
				dialog.set_tran_state(SipTransactionState::Completed);
				dialog.state = DialogState::Answered;

				let buf = dialog.generate_inv_ack();
				dialog.send_to_remote(buf);
				dialog.set_sdp(&sip_data.body)?;
				//正常收接通确认消息.向业务发送
				dialog.send_to_business(ChannelEvent::ChannelAnswer(dialog.id));
				dialog.send_to_business(ChannelEvent::ChannelCallState(
					dialog.id,
					ChannelState::Answered,
				));
			}
			(300..=699, SipTransactionState::Callin) | (300..=699, SipTransactionState::Proceeding) => {
				dialog.retry_time = Duration::ZERO;
				dialog.start_time = get_now_duration();
				dialog.over_time = SipTimeOver::Finish(WAIT_REPEAT_TIME);
				dialog.wait_resp_method = WaitSipMessage::None;
				dialog.state = DialogState::NeedKill;
				dialog.set_tran_state(SipTransactionState::Completed);

				let buf = dialog.generate_inv_ack();
				dialog.send_to_remote(buf);

				//正常收失败挂断确认消息.向业务发送结束通话
				dialog.send_to_business(ChannelEvent::ChannelHangup(
					dialog.id,
					sip_data.to_hangup_reason(),
				));
				dialog.send_to_business(ChannelEvent::ChannelCallState(
					dialog.id,
					ChannelState::Hangup,
				));
			}

			//这里是处理重传,只回复
			(200..=699, SipTransactionState::Completed) => {
				let buf = dialog.generate_inv_ack();
				dialog.send_to_remote(buf);
			}
			_ => debug!(
				"收到无效回复消息.sip:{:?},状态:{:?}",
				sip_data,
				dialog.tran_state()
			),
		},
		SipDirection::Request(_) => debug!("inv_cli不应该收到请求"),
	}

	Ok(())
}

///处理事务收到的命令消息
#[inline]
pub fn handle_command_msg(dialog: &mut Dialog, cmd_msg: CommandMsg) -> ResultNull {
	match cmd_msg {
		CommandMsg::KillChannel(_) | CommandMsg::HangupChannel(..) => {
			if dialog.tran_state() > SipTransactionState::Proceeding {
				dialog.state = DialogState::NeedKill;
				return Ok(());
			}

			let buf = dialog.generate_cancel();
			send_wait_resp(dialog, WaitSipMessage::Ok, buf);
			dialog.send_to_business(ChannelEvent::ChannelHangup(
				dialog.id,
				EndReason::InitiativeHangup,
			))
		}
		//以下操作应该在上层进行处理
		CommandMsg::Originate { .. } | CommandMsg::BridgeChannel(..) => {
			error!("事务处理不应该收到当前事务.应在上层处理")
		}
		//未列出的代表直接忽略
		CommandMsg::SetVar | _ => debug!("收到一个无效的命令消息."),
	}
	Ok(())
}

///处理事务结束的操作..
/// 返回true表示事务结束时dialog同时结束.
#[inline]
pub fn end_tran(dialog: &mut Dialog) -> ResultEx<bool> {
	dialog.last_send_bytes = None;
	dialog.tran_handler = SipTransaction::NoN;

	Ok(dialog.state != DialogState::Answered)
}

#[inline]
pub fn handle_time_over(dialog: &mut Dialog, to: SipTimeOver) -> ResultNull {
	match to {
		//业务超时,需要发起挂断操作
		SipTimeOver::CallOvertime(_) => {
			let buf = dialog.generate_cancel();
			send_wait_resp(dialog, WaitSipMessage::Ok, buf);
		}

		//只要是超时,则不算成功创建dialog
		SipTimeOver::TranOvertime(_) => {
			dialog.set_tran_state(SipTransactionState::Terminated);
			dialog.send_to_business(ChannelEvent::ChannelHangup(dialog.id, EndReason::Overtime));
		}
		SipTimeOver::Zero => dialog.set_tran_state(SipTransactionState::Terminated),
		SipTimeOver::Retry(_) => {
			trace!("inv_client这里进行重发");
			dialog.retry_send()?;
		}
		_ => {}
	}

	//超时以后的判断.
	if dialog.tran_state() == SipTransactionState::Completed {
		dialog.set_tran_state(SipTransactionState::Terminated);
	}

	Ok(())
}
